#ifndef TABU_H
#define TABU_H
#include <Eigen/Core>
#include <list>
#include <vector>

using namespace std;
using namespace Eigen;

struct TabuItem
{
    unsigned short posX;
    unsigned short posY;
    int nVal;
    TabuItem(int posX,int posY,int nVal)
    {
        this->posX = posX;
        this->posY = posY;
        this->nVal = nVal;
    }
};

struct NeighborItem
{
    MatrixX<int> solve;
    int posX;
    int posY;
};

class Tabu
{
public:
    typedef list<TabuItem> TabuList ;
    //最好解 交换的两个数
    typedef NeighborItem BestNeighborType;

public:
    /**
     * @brief Tabu
     * @param nTabuSize 禁忌表大小
     * @param nNeighbor 搜索邻域大小
     */
    Tabu(int nTabuSize,int nNeighbor);
    ~Tabu();
    /**
     * @brief run
     * @param mat 算例矩阵
     * @param firstSolve 初始解
     * @param maxStep 迭代步数
     */
    void run(MatrixX<int> &mat,MatrixX<int> &firstSolve,int maxStep);

private:
    /**
     * @brief addTabu 添加到禁忌表
     * @param vec
     * @param posX
     * @param posY
     * @param nVal
     * @param bIsBest
     */
    void addTabu(int posX,int posY,int nVal,bool bIsBest);
    /**
     * @brief getBestNeighbor 获取领域内最好的解
     * @param mat
     * @param bestNeighbor
     * @param nStartIndex
     */
    void getBestNeighbor(MatrixX<int> &mat, BestNeighborType &bestNeighbor, int nStartIndex);
    /**
     * @brief isBetterNeighb 判断是否是更好的解
     * @param mat
     * @param solve1
     * @param solve2
     * @param bestVal
     * @return
     */
    inline bool isBetterNeighb(MatrixX<int> &mat, MatrixX<int> &solve1, MatrixX<int> &solve2,int &bestVal);
    inline bool isBetterNeighb(MatrixX<int> &mat, MatrixX<int> &solve1, MatrixX<int> &solve2);
    /**
     * @brief calcCost 计算开销
     * @param mat
     * @param firstSolve
     * @return
     */
    inline int calcCost(MatrixX<int> &mat,MatrixX<int> &firstSolve);

private:
    ///
    /// \brief m_nParallelNum 并行数量
    ///
    int m_nParallelNum = 1;
    std::vector<BestNeighborType> m_matVec;
    TabuList *m_pTabu = nullptr;
    int m_nTabuSize = 0;
    const int m_nNeighbor = 0;
};

#endif // TABU_H
